using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace HalconDotNet
{
	internal class HTupleDouble : HTupleImplementation
	{
		protected double[] d;

		public override double[] DArr
		{
			get
			{
				return d;
			}
			set
			{
				SetArray(value, copy: false);
			}
		}

		public override HTupleType Type => HTupleType.DOUBLE;

		protected override Array CreateArray(int size)
		{
			return new double[size];
		}

		protected override void NotifyArrayUpdate()
		{
			d = (double[])data;
		}

		public HTupleDouble(double d)
		{
			SetArray(new double[1]
			{
				d
			}, copy: false);
		}

		public HTupleDouble(double[] d, bool copy)
		{
			SetArray(d, copy);
		}

		public HTupleDouble(float[] f)
		{
			SetArray(f, copy: true);
		}

		internal override void PinTuple()
		{
			Monitor.Enter(this);
			if (pinCount == 0)
			{
				pinHandle = GCHandle.Alloc(d, GCHandleType.Pinned);
			}
			pinCount++;
			Monitor.Exit(this);
		}

		public override HTupleElements GetElement(int index, HTuple parent)
		{
			return new HTupleElements(parent, this, index);
		}

		public override HTupleElements GetElements(int[] indices, HTuple parent)
		{
			if (indices == null || indices.Length == 0)
			{
				return new HTupleElements();
			}
			return new HTupleElements(parent, this, indices);
		}

		public override void SetElements(int[] indices, HTupleElements elements)
		{
			HTupleElementsDouble hTupleElementsDouble = new HTupleElementsDouble(this, indices);
			hTupleElementsDouble.setD(elements.DArr);
		}

		public override double[] ToDArr()
		{
			return (double[])ToArray(typeD);
		}

		public override float[] ToFArr()
		{
			float[] array = new float[iLength];
			for (int i = 0; i < iLength; i++)
			{
				array[i] = (float)d[i];
			}
			return array;
		}

		public override int CopyToDArr(double[] dst, int offset)
		{
			Array.Copy(d, 0, dst, offset, iLength);
			return iLength;
		}

		public override int CopyToOArr(object[] dst, int offset)
		{
			for (int i = 0; i < iLength; i++)
			{
				dst[i + offset] = d[i];
			}
			return iLength;
		}

		public override int CopyFrom(HTupleImplementation impl, int offset)
		{
			return impl.CopyToDArr(d, offset);
		}

		public override void Store(IntPtr proc, int parIndex)
		{
			HalconAPI.HCkP(proc, HalconAPI.GetInputTuple(proc, parIndex, out IntPtr tuple));
			StoreData(proc, tuple);
		}

		protected override void StoreData(IntPtr proc, IntPtr tuple)
		{
			PinTuple();
			HalconAPI.SetDArrPtr(tuple, d, iLength);
		}

		public static int Load(IntPtr tuple, out HTupleDouble data)
		{
			HalconAPI.GetTupleLength(tuple, out int length);
			double[] doubleArray = new double[length];
			int dArr = HalconAPI.GetDArr(tuple, doubleArray);
			data = new HTupleDouble(doubleArray, copy: false);
			return dArr;
		}
	}
}
